package com.demo.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

public class NioClientChannel {
    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        SocketAddress address = new InetSocketAddress(8188);
        Selector selector = Selector.open();
        socketChannel.connect(address);
        //非阻塞连接需要注册connect事件
        socketChannel.register(selector, SelectionKey.OP_CONNECT);
        //启动机器人发送消息
        new Thread(new RobotThread()).start();
        for (;;){
            if(selector.select()>0){
                Set<SelectionKey> keys = selector.selectedKeys();
                Iterator<SelectionKey> it = keys.iterator();
                while (it.hasNext()){
                    SelectionKey key = it.next();
                    it.remove();
                    if(key.isConnectable()){
                        SocketChannel channel = (SocketChannel) key.channel();
                        if(channel.isConnectionPending()){
                            channel.finishConnect();//完成连接动作
                        }
                        channel.configureBlocking(false);
                        channel.write(ByteBuffer.wrap("hello,i am wally!".getBytes()));
                        channel.register(selector,SelectionKey.OP_READ | SelectionKey.OP_WRITE);
                    }
                    if(key.isReadable()){
                        SocketChannel channel = (SocketChannel) key.channel();
                        ByteBuffer dst = ByteBuffer.allocate(10);
                        try{
                            while (channel.read(dst) > 0){
                                dst.flip();
                                while (dst.remaining() > 0){
                                    System.out.print((char)dst.get());
                                }
                                dst.clear();
                            }
                        }catch (IOException e){
                            e.printStackTrace();
                            key.cancel();
                            channel.socket().close();
                            channel.close();
                        }
                        System.out.println();
                    }
                    if(key.isWritable()){
                        try {
                            String message = synQueue.poll(1, TimeUnit.SECONDS);
                            if(message != null){
                                SocketChannel channel = (SocketChannel) key.channel();
                                channel.write(ByteBuffer.wrap(message.getBytes()));
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        }

    }
    private static final SynchronousQueue<String> synQueue = new SynchronousQueue();
    static class RobotThread implements Runnable{
        @Override
        public void run() {
            for(;;){
                try {
                    synQueue.put("iam boring,talk to me");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sleeping(1500);
            }
        }
    }
    static void sleeping(long n){
        try {
            Thread.currentThread().sleep(n);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
